"""
    基于process的多进程网络
"""

from multiprocessing import Process  # 多进程
from socket import *  # 网络
import os
import signal  # 系统托管进程

HOST = '0.0.0.0'
POST = 18693
ADDR = (HOST, POST)


class MyProcess:
    def __init__(self):
        """
            创建套接字初始化网络
        """
        signal.signal()
        self.__sockfd = socket() # 创建套接字
        self.__sockfd.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # 端口重用
        self.__sockfd.bind(ADDR) # 绑定IP端口
        self.__sockfd.listen(5)  # 最多链接5个客户端
        
        # 多进程列表
        self.__pr_list = [self.__handle, self.__fun1]
        # 多进程完成列表
        self.__or_list = []
        
    # 网络服务
    def __start_server(self):
        """
            开启服务
        """
        while True:
            print("等待链接中...")
            
            try:
                connfd,addr = self.__sockfd.accept() # 阻塞, 等待客户端连接
                print(f"有客户端连接: {addr}")
            except KeyboardInterrupt:
                print("检测到客户端非正常退出!")
                connfd._exit(0) # 服务结束
            except Exception as e:
                print(f"遇到了错误: {e}")
                continue
            
            # 转多进程处理
            self.__current_client(connfd, addr)  # 如果需要等待客户端连接才执行子进程,则不需要改动,否则多进程处理应在阻塞之前产生
    
    # 主线程多任务
    def __current_client(self, data, addr):
        for item in self.__pr_list:
            so = Process(target=item, args=(data, addr)) # 实例化进程对象
            so.daemon = True  # 父进程退出所有子进程也要退出
            so.start() # 开始子进程
            self.__or_list.append(item) # 追加
        
        # 回收
        [so.join() for i in self.__or_list]
    
    # 子进程
    def __handle(self, *args):  # 如果有多个子进程同时执行, 传参必须一样,否则报错
        """
        子进程
        """
        c = args[0]
        d = args[1]
        while True:
            data = c.recv(1024) # 收取消息
            if not data:
                break
            print(f"客户端: {d}发送的消息: {data.decode()}")
            c.send('ok'.encode())
        c.close()
        
    # 子进程1
    def __fun1(self, *args):
        print(f"这是第二个进程.{args[0], {args[1]}}")
    
    
    # main
    def start_(self):
        self.__start_server()


ls = MyProcess()
ls.start_()